#include <iostream>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
#include <cstdlib>
#include <vector>

// 读写锁是pthread第三方库封装的

// 读写锁与生产消费模型的区别
// 1.读者写者之间是互斥的
// 2.写者写者之间是互斥的
// 3.读者读者之间没什么太大关系,多个读者可以同时访问
// 这是读写与生产消费之间最大的区别:读者不会拿数据,消费者会消费数据

int shared_date = 0;
pthread_rwlock_t lock;
const int gwrite_num = 10;
const int gread_num = 2;
int gtotal = gwrite_num + gread_num;

void *write(void *args)
{
    int num = *(int *)args;
    while (true)
    {
        pthread_rwlock_wrlock(&lock); // 写者要写入,写者加锁
        shared_date = rand() % 100 + 1;
        std::cout << "写者-" << num << "写入新的数据:" << shared_date << std::endl;
        sleep(1);
        pthread_rwlock_unlock(&lock);
    }
    return nullptr;
}
void *read(void *args)
{
    int num = *(int *)args;
    while (true)
    {
        pthread_rwlock_rdlock(&lock); // 读者要读,读者加锁
        int date = shared_date;
        std::cout << "读者-" << num << "读取到数据:" << date << std::endl;
        sleep(2);
        pthread_rwlock_unlock(&lock);
    }
}
int main()
{
    srand(time(nullptr));
    pthread_rwlock_init(&lock, nullptr);
    pthread_t threads[gtotal]; // 包含了所有读线程和写线程
    for (int i = 0; i < gwrite_num; i++)
    {
        int *id = new int(i);
        pthread_create(&threads[i], nullptr, write, id);
    }
    for (int i = gtotal - gwrite_num; i < gtotal; i++)
    {
        int *id = new int(i - gread_num);
        pthread_create(&threads[i], nullptr, read, id);
    }
    for (int i = 0; i < gtotal; i++)
    {
        pthread_join(threads[i], nullptr);
    }
    pthread_rwlock_destroy(&lock);
    return 0;
}